package com.tqjc.system.core.pipeline.thread;

import com.tqjc.business.interactivewithscan.entity.Coord;
import com.tqjc.system.common.constant.AddTaskConstant;
import com.tqjc.system.common.constant.ConfigConstant;
import com.tqjc.system.common.constant.GlobalConstant;
import com.tqjc.system.common.constant.RemoteURLConstant;
import com.tqjc.system.common.entity.BO.PLCWriteRequestParamBO;
import com.tqjc.system.common.entity.BO.ResponseLabelDataBO;
import com.tqjc.system.common.entity.BO.SingleTaskMaterialBO;
import com.tqjc.system.common.enums.*;
import com.tqjc.system.common.exception.AddTaskException;
import com.tqjc.system.core.pipeline.util.AddTaskUtil;
import com.tqjc.system.core.pipeline.util.ScanUtils;
import com.tqjc.system.core.scan.thread.AsynTankCarScanThread;
import com.tqjc.system.core.threadpool.ThreadPoolManager;
import com.tqjc.system.core.util.DateUtils;
import com.tqjc.system.core.util.PLCHttpsUtils;
import com.tqjc.system.core.util.SpringUtils;
import com.tqjc.system.core.websocket.TaskExecutionWebSocketService;
import com.tqjc.system.system.entity.SysAddDetailTaskEntity;
import com.tqjc.system.system.entity.SysPLCRecordEntity;
import com.tqjc.system.system.entity.SysTaskErrorInfoEntity;
import com.tqjc.system.system.service.SysAddDetailTaskService;
import com.tqjc.system.system.service.SysPLCRecordService;
import com.tqjc.system.system.util.SystemUtils;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;


/**
 * @author 86195
 * @version 1.0
 * @description 天车执行单个加料任务线程
 * @date 2023/10/18 15:02
 */
@Slf4j
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Getter
public class CarDoingSingleAddTaskThread extends AbstrCarDoingAddTaskThread{


    private SingleTaskMaterialBO taskMaterialBO;



    /**
     * 任务暂停标识  true:任务暂停中
     */
    private boolean taskFlag;

    /**
     * 槽车到位信号    false:未到位   true:已到位
     */
    private boolean tankCarReadyFlag;




    @Override
    public void run() {
        //任务id
        String taskId = taskMaterialBO.getTaskId();
        Long idKey = taskMaterialBO.getIdKey();
        String workingSpanNo = taskMaterialBO.getWorkingSpanNo();
        log.info("任务id：{}在跨：{}处理单个任务开始",taskId,workingSpanNo);
        //干活的天车
        CarEnum workingCarEnum = taskMaterialBO.getCarEnum();
        String materialNo = taskMaterialBO.getMaterialNo();
        int areaNum = taskMaterialBO.getAreaNum();
        //目标位置
        String targetValue;

        //开始时间
        LocalDateTime startDate;

        //结束时间
        LocalDateTime endDate;

        //plc信息对象
        SysPLCRecordEntity plcRecord;

        SysPLCRecordService plcRecordService = SpringUtils.getBean(SysPLCRecordService.class);


        //作业类型
        String taskType;
        //作业地址
        String taskPlace;
        //双车大车运行状态
        boolean carRunningFlag;
        SysAddDetailTaskService sysAddDetailTaskService = SpringUtils.getBean("SysAddDetailTaskService");


        //天车信息枚举
        CarPLCInfoEnum carPLCInfoEnum = CarPLCInfoEnum.getCarNoEnum(workingSpanNo, workingCarEnum.getCarNo());
        String macSN = carPLCInfoEnum.getMacSN();
        //任务开始
        SysAddDetailTaskEntity sysAddDetailTaskEntity = SysAddDetailTaskEntity.builder().idKey(idKey)
                .status(TaskStatusEnum.STATUS_DOING.getStatus()).carName(macSN).build();
        //异步线程更新数据
        ThreadPoolManager.getInstance().execute(new DataUpdateThread(sysAddDetailTaskService,sysAddDetailTaskEntity));

        try {


            String tankCarNo = taskMaterialBO.getTankCarNo();
            TankCarNoEnum tankCarNoEnum = TankCarNoEnum.getEnumByCarNo(tankCarNo);
            String tankCarName = tankCarNoEnum.getTankName();
            //槽车参数Map
            Map<String,String> tankCarParamMap = new HashMap(2);



            tankCarParamMap.put(GlobalConstant.STRING_SN,GlobalConstant.TANK_CAR_SN_VAL);

            //天车参数Map
            Map<String,String> carParamMap = new HashMap(2);
            //另一台车参数Map
            Map<String,String> otherCarMap = new HashMap(2);
            Map<String, String> carSNMap = SystemUtils.Sys_carInfo.get(ConfigConstant.CONFIG_TYPE_CAR_BAK_SN);
            String carSN = carSNMap.get(carPLCInfoEnum.getMacSN());
            carParamMap.put(GlobalConstant.STRING_SN,carSN);
            otherCarMap.put(GlobalConstant.STRING_SN,carSNMap.get(carPLCInfoEnum.getOtherMacSN()));



            //天车模式参数Map
            Map modelParamMap = new HashMap(2);

            modelParamMap.put(GlobalConstant.STRING_SN,carSN);
            modelParamMap.put(GlobalConstant.STRING_LABEL,carPLCInfoEnum.getMacSN() + GlobalConstant.CAR_MODEL_LABEL);
            while (true){

//                Coord grabPoint = ScanUtils.getSpanGrabPoint(workingSpanNo, carPLCInfoEnum.getCarNo(), materialNo, areaNum);
                Coord grabPoint = ScanUtils.getAreaPointBO(workingSpanNo, materialNo, AddTaskConstant.AREA_SCAN_TYPE_SUCK);

                if(grabPoint == null){
                //扫描没有点，则报警任务暂停
                    log.error("单线程执行任务时，跨区为：{},carNo为：{},没有获取到抓点",workingSpanNo,workingCarEnum.getCarNo());
                    throw new AddTaskException("没有获取到抓点");
                }
//                Coord grabPoint = new Coord();
//                //抓点  174527   32685   17085
//                //放点   178296   34236    17589
//                grabPoint.setX(24470);
//                grabPoint.setY(27950);
//                grabPoint.setZ(13801);


                taskType = AddTaskConstant.CAR_TASK_TYPE_SUCK;
                taskPlace = AddTaskConstant.CAR_TASK_PLACE_MATERIAL;
                //plcInfoArray  二维数组  大车目标坐标[] 小车目标坐标[]  起升目标坐标[] 作业类型[]  作业地址[] 任务运行[]
                //记录PLC表
                plcRecord = SysPLCRecordEntity.builder().taskId(taskId).relationIdKey(String.valueOf(idKey)).carName(carPLCInfoEnum.getMacSN())
                        .indexInfo(grabPoint.getIndexInfo()).actionInfo(AddTaskConstant.ACT_SUCK).targetInfo("库区："+areaNum).build();
                plcRecordService.save(plcRecord);

                carRunningFlag = AddTaskUtil.isCarRunningStatus(carSN, carPLCInfoEnum.getMacSN(), carPLCInfoEnum.getOtherMacSN() );
                if(!carRunningFlag){
                    throw new AddTaskException("单线程执行任务时，双车的大车运行状态不是自动,跨区为："+workingSpanNo);
                }
                while (true){

                    otherCarMap.put(GlobalConstant.STRING_LABEL,carPLCInfoEnum.getOtherMacSN() + GlobalConstant.CAR_X_INDEX_LABEL);
                    int otherCarIndex = Integer.valueOf(this.getValByLabel(otherCarMap));
                    boolean conflictFlag = comparePosition(workingCarEnum, grabPoint.getX(), otherCarIndex);
                    if(conflictFlag){
                        log.info("单线程执行任务时，跨区为：{},carNo为：{},没有冲突，继续运行",workingSpanNo,workingCarEnum.getCarNo());
                        break;
                    }
                    Thread.sleep(1*1000);
                    log.info("单线程执行任务时，跨区为：{},carNo为：{},存在冲突,循环判断冲突",workingSpanNo,workingCarEnum.getCarNo());

                }


                startDate = LocalDateTime.now();
                this.writeMoreVal(carPLCInfoEnum,taskType,taskPlace,grabPoint);

//                Object[][] plcInfoArray = carPLCInfoEnum.getPLCInfoArray();
//                for(int i = 0;i < plcInfoArray.length;i++){
//                    //info  一位数组[地址,数据类型,label]
//                    Object[] info = plcInfoArray[i];
//                    //设置value
//                    String value = this.getValue(taskType,taskPlace,grabPoint,i);
//                    this.writeOpt(info,value,carPLCInfoEnum.getMacSN());
//                }
                //2.判断槽车是否到位
                if(!tankCarReadyFlag){
                    while (true){
                        boolean tankCarScanActFinish = ScanUtils.getTankCarScanActFinish(tankCarNoEnum);
                        log.info("加料单线程判断槽车是否到位。。。。，当前槽车到位信号为：{}",tankCarScanActFinish);
                        //天车模式flag  false:手动  true:自动
                        boolean modelFlag = Boolean.valueOf(this.getValByLabel(modelParamMap));

                        if(!modelFlag){
                            //模式为自动时，线程结束
                            log.info("任务id：{},工作跨：{},单线程加料线程任务。判断槽车是否到位时，模式切换至手动模式，线程退出",taskId,workingSpanNo);
                            //模式为自动时，线程结束
                            SysAddDetailTaskEntity errEntity = SysAddDetailTaskEntity.builder().idKey(idKey)
                                    .status(TaskStatusEnum.STATUS_ERROR.getStatus()).errMsg("判断槽车是否到位时，模式切换至手动模式，线程退出").build();
                            sysAddDetailTaskService.updateById(errEntity);
                            return;

                        }

//                        if(taskFlag){
//                            throw new AddTaskException("双车加料线程执行任务时，任务监控点位出现故障");
//                        }

                        if(taskFinishFlag){
                            log.error("任务id：{},工作跨：{},单线程加料线程任务。判断槽车是否到位时。任务标识为已完成",taskId,workingSpanNo);
                            throw new AddTaskException("双车加料线程执行任务时，任务手动置为完成状态");
                        }


                        if (tankCarScanActFinish){
                            tankCarReadyFlag = true;
                            break;
                        }
                        Thread.sleep(1*1000);
                    }
                }
                if(AddTaskConstant.TANKCAR_SCAN_USE_FLAG){
                    //启用槽车扫描，异步发起槽车扫描
                    log.info("启动异步槽车扫描线程");
                    ThreadPoolManager.getInstance().execute(AsynTankCarScanThread.builder().tankCarNoEnum(tankCarNoEnum).spanNo(workingSpanNo).build());
                }

                //3.去放点,获取当前槽车重量信息           label
                carParamMap.put(GlobalConstant.STRING_LABEL, tankCarNoEnum.getWeightLabel());
                ResponseLabelDataBO responseLabelDataBO = PLCHttpsUtils.sendPost(RemoteURLConstant.URL_READBC, carParamMap, ResponseLabelDataBO.class);
                Map<String, String> oldWeightcontent = responseLabelDataBO.getContent();
                //之前重量
                float oldWeight = oldWeightcontent != null ? Float.valueOf(oldWeightcontent.get("currentVal").toLowerCase() ): 0;
                //判断吸动作是否完成
                while (true){
//                    if(taskFlag){
//                        throw new AddTaskException("单线程执行任务时，任务监控点位出现故障");
//                    }
                    carParamMap.put(GlobalConstant.STRING_LABEL, macSN + GlobalConstant.SUCK_FINISH_LABEL);
                    boolean suckFlag = Boolean.valueOf(this.getValByLabel(carParamMap));
                    boolean modelFlag = Boolean.valueOf(this.getValByLabel(modelParamMap));

                    if(!modelFlag){
                        //模式为自动时，线程结束
                        log.info("任务id：{},工作跨：{},单车执行加料任务。执行吸料动作，模式切换至手动模式，线程退出",taskId,workingSpanNo);
                        SysAddDetailTaskEntity errEntity = SysAddDetailTaskEntity.builder().idKey(idKey)
                                .status(TaskStatusEnum.STATUS_ERROR.getStatus()).errMsg("执行吸料动作时，模式切换至手动模式，线程退出").build();
                        sysAddDetailTaskService.updateById(errEntity);
                        endDate = LocalDateTime.now();
                        int timeInterval = DateUtils.getTimeInterval(startDate, endDate);
                        SysPLCRecordEntity PLCUpdateEntity = SysPLCRecordEntity.builder().idKey(plcRecord.getIdKey())
                                .status(PLCRecordStatusEnum.PLC_STATUS_SUCC.getStatus()).spendTime(timeInterval).build();
                        plcRecordService.updateById(PLCUpdateEntity);
                        return;
                    }


//                    if(taskFlag){
//                        throw new AddTaskException("单车执行吸料动作时，任务监控点位出现故障");
//                    }

                    if(taskFinishFlag){
                        log.error("任务id：{},工作跨：{},单线程加料线程任务。判断吸料任务是否完成。任务标识为已完成",taskId,workingSpanNo);
                        throw new AddTaskException("双车加料线程执行任务时，任务手动置为完成状态");
                    }

                    if(suckFlag){
                        //复位天车运行点位
                        Object[] carExecuteInfo = carPLCInfoEnum.getPLCInfoArray()[5];
                        PLCWriteRequestParamBO paramBO = PLCWriteRequestParamBO.builder().dataType((Integer) carExecuteInfo[1])
                                .address((String) carExecuteInfo[0]).macSN(macSN).label((String) carExecuteInfo[2]).build();
                        paramBO.setValue(AddTaskConstant.CAR_FORBID_MOVE);
                        PLCHttpsUtils.write(RemoteURLConstant.URL_WRITEBC,paramBO);

                        break;
                    }
                    Thread.sleep(1*1000);

                }


                taskType = AddTaskConstant.CAR_TASK_TYPE_PUT;
                taskPlace = AddTaskConstant.CAR_TASK_PLACE_STEEL_CAR;
                //ScanUtils.getTankCarPoint(tankCarNoEnum.getTankCarNo(),carPLCInfoEnum.getScanType());
                //Coord  putPointData = ScanUtils.getTestTankCarPoint(workingSpanNo,tankCarNoEnum,"1");
                Coord putPointData = ScanUtils.getTankCarPoint(tankCarNoEnum, workingSpanNo);
                if(putPointData == null){
                    throw new AddTaskException("没有获取到槽车扫描点数据");
                }


//                Coord putPointData = new Coord();
//                //111350
//                putPointData.setX(111058);
//                putPointData.setY(15395);
//                putPointData.setZ(10746);




                startDate = LocalDateTime.now();
                //记录PLC表
                plcRecord = SysPLCRecordEntity.builder().taskId(taskId).relationIdKey(String.valueOf(idKey)).carName(carPLCInfoEnum.getMacSN())
                        .indexInfo(putPointData.getIndexInfo()).actionInfo(AddTaskConstant.ACT_PUT).targetInfo("槽车："+tankCarName).build();
                plcRecordService.save(plcRecord);

                carRunningFlag = AddTaskUtil.isCarRunningStatus(carSN, carPLCInfoEnum.getMacSN(), carPLCInfoEnum.getOtherMacSN());
                if(!carRunningFlag){
                    throw new AddTaskException("单线程执行任务时，双车的大车运行状态不是自动,跨区为："+workingSpanNo);
                }

                while (true){

                    otherCarMap.put(GlobalConstant.STRING_LABEL,carPLCInfoEnum.getOtherMacSN() + GlobalConstant.CAR_X_INDEX_LABEL);
                    int otherCarIndex = Integer.valueOf(this.getValByLabel(otherCarMap));
                    boolean conflictFlag = comparePosition(workingCarEnum, putPointData.getX(), otherCarIndex);
                    if(conflictFlag){
                        log.info("单线程执行任务时，跨区为：{},carNo为：{},放动作没有冲突，继续运行",workingSpanNo,workingCarEnum.getCarNo());
                        break;
                    }
                    Thread.sleep(1*1000);
                    log.info("单线程执行任务时，跨区为：{},carNo为：{},放动作存在冲突,循环判断冲突",workingSpanNo,workingCarEnum.getCarNo());

                }
                this.writeMoreVal(carPLCInfoEnum,taskType,taskPlace,putPointData);

//                for(int i = 0;i < plcInfoArray.length;i++){
//                    //info  一位数组[地址,数据类型,label]
//                    Object[] info = plcInfoArray[i];
//                    //设置value
//                    String value = this.getValue(taskType,taskPlace,putPointData,i);
//                    this.writeOpt(info,value,carPLCInfoEnum.getMacSN());
//                }


                //判断放动作是否完成
                while (true){

                    carParamMap.put(GlobalConstant.STRING_LABEL, macSN + GlobalConstant.PUT_FINISH_LABEL);

                    boolean putFlag = Boolean.valueOf(this.getValByLabel(carParamMap));

                    boolean modelFlag = Boolean.valueOf(this.getValByLabel(modelParamMap));

//                    if(taskFlag){
//                        throw new AddTaskException("单线程执行任务时，任务监控点位出现故障");
//                    }

                    if(taskFinishFlag){
                        log.error("任务id：{},工作跨：{},单线程加料线程任务。判断放料任务是否完成。任务标识为已完成",taskId,workingSpanNo);
                        throw new AddTaskException("双车加料线程执行任务时，任务手动置为完成状态");
                    }

                    if(!modelFlag){
                        //模式为自动时，线程结束
                        log.info("任务id：{},工作跨：{},单车执行加料任务。放下动作完成，模式切换至手动模式，线程退出",taskId,workingSpanNo);
                        SysAddDetailTaskEntity errEntity = SysAddDetailTaskEntity.builder().idKey(idKey)
                                .status(TaskStatusEnum.STATUS_ERROR.getStatus()).errMsg("执行放下动作时，模式切换至手动模式，线程退出").build();
                        sysAddDetailTaskService.updateById(errEntity);
                        return;
                    }

                    if(putFlag){
                        //天车执行执行复位
                        Object[] carExecuteInfo = carPLCInfoEnum.getPLCInfoArray()[5];
                        PLCWriteRequestParamBO paramBO = PLCWriteRequestParamBO.builder().dataType((Integer) carExecuteInfo[1])
                                .address((String) carExecuteInfo[0]).macSN(macSN).label((String) carExecuteInfo[2]).build();
                        paramBO.setValue(AddTaskConstant.CAR_FORBID_MOVE);
                        PLCHttpsUtils.write(RemoteURLConstant.URL_WRITEBC,paramBO);
                        break;
                    }
                    Thread.sleep(1*1000);
                }

                //获取本次本次重量
                carParamMap.put(GlobalConstant.STRING_LABEL, tankCarNoEnum.getWeightLabel());
                ResponseLabelDataBO nowWeightLableBO = PLCHttpsUtils.sendPost(RemoteURLConstant.URL_READBC, carParamMap, ResponseLabelDataBO.class);
                Map<String, String> nowWeightContent = nowWeightLableBO.getContent();
                //本次重量
                float nowWeight = nowWeightContent != null ? Float.valueOf(nowWeightContent.get("currentVal").toLowerCase() ): 0;


                float addWeight = nowWeight - oldWeight;
                //5.放动作完成后，重量计算。判断当前重量是否满足目标重量。更新数据库
                SysAddDetailTaskEntity detailTaskEntity = sysAddDetailTaskService.getMaterial(taskId,taskMaterialBO.getMaterialNo());
                //更新PLC操作
                endDate = LocalDateTime.now();
                int timeInterval = DateUtils.getTimeInterval(startDate, endDate);
                SysPLCRecordEntity plcUpdateEntity = SysPLCRecordEntity.builder().idKey(plcRecord.getIdKey())
                        .status(PLCRecordStatusEnum.PLC_STATUS_SUCC.getStatus()).spendTime(timeInterval).addWeight(addWeight).build();
                plcRecordService.updateById(plcUpdateEntity);




//                if(addWeight == 0){
//                    //本次重量为0,则库区已无物料
//                    //任务已完成
//                    SysAddDetailTaskEntity updateEntity = SysAddDetailTaskEntity.builder().idKey(detailTaskEntity.getIdKey())
//                            .status(TaskStatusEnum.STATUS_ERROR.getStatus()).errMsg("库区无物料").build();
//                    //异步线程更新数据
//                    ThreadPoolManager.getInstance().execute(new DataUpdateThread(sysAddDetailTaskService,updateEntity));
//                    AddTaskConstant.TASK_WORKING_MATERIAL_MAP.remove(taskId);
//                    break;
//                }
                float actualWeight = detailTaskEntity.getActualWeight() + addWeight;
                actualWeight = Float.valueOf(String.format("%.6f", actualWeight));

                if(TaskStatusEnum.STATUS_COMPLETE.equals(detailTaskEntity.getStatus()) ){
                    log.info("任务id：{}在跨：{}处理单个任务结束,任务状态已手动翻转至完成",taskId,workingSpanNo);

                    //任务已完成
                    SysAddDetailTaskEntity updateEntity = SysAddDetailTaskEntity.builder().idKey(detailTaskEntity.getIdKey())
                            .status(TaskStatusEnum.STATUS_COMPLETE.getStatus()).errMsg("任务状态手动翻转至完成").actualWeight(actualWeight).build();
                    //异步线程更新数据
                    ThreadPoolManager.getInstance().execute(new DataUpdateThread(sysAddDetailTaskService,updateEntity));
                    break;
                }

                //5若不满足目标重量，重新执行抓放动作   计算公式：任务已加重量 + 本次添加重量 - 任务的目标重量  < 1000 单位：kg
                if(Math.abs(actualWeight - detailTaskEntity.getTargetWeight()) <= 1 || actualWeight >  detailTaskEntity.getTargetWeight() ){
                    log.info("任务id：{}在跨：{}处理单个任务结束",taskId,workingSpanNo);

                    //任务已完成
                    SysAddDetailTaskEntity updateEntity = SysAddDetailTaskEntity.builder().idKey(detailTaskEntity.getIdKey())
                            .status(TaskStatusEnum.STATUS_COMPLETE.getStatus()).actualWeight(actualWeight).build();
                    //异步线程更新数据
                    ThreadPoolManager.getInstance().execute(new DataUpdateThread(sysAddDetailTaskService,updateEntity));
                    break;
                }
                //更新任务的重量信息
                SysAddDetailTaskEntity updateEntity = SysAddDetailTaskEntity.builder().idKey(detailTaskEntity.getIdKey())
                        .actualWeight(actualWeight).build();
                ThreadPoolManager.getInstance().execute(new DataUpdateThread(sysAddDetailTaskService,updateEntity));


            }
            log.info("任务id：{}在跨：{}处理单个任务结束",taskId,workingSpanNo);
            String key = workingSpanNo + "_" + taskMaterialBO.getCarEnum().getCarNo();
            taskFinishFlag = true;
            goSafePosition(carPLCInfoEnum);
            AddTaskUtil.updateCarIndex(key,null);
            while (true){
                carParamMap.put(GlobalConstant.STRING_LABEL, macSN + GlobalConstant.MOVE_FINISH_LABEL);
                boolean moveFlag = Boolean.valueOf(this.getValByLabel(carParamMap));
                if(moveFlag){
                    Object[] carExecuteInfo = carPLCInfoEnum.getPLCInfoArray()[5];
                    //天车动作执行复位
                    PLCWriteRequestParamBO paramBO = PLCWriteRequestParamBO.builder().dataType((Integer) carExecuteInfo[1])
                            .address((String) carExecuteInfo[0]).macSN(macSN).label((String) carExecuteInfo[2]).build();
                    paramBO.setValue(AddTaskConstant.CAR_FORBID_MOVE);
                    PLCHttpsUtils.write(RemoteURLConstant.URL_WRITEBC,paramBO);
                    break;
                }
                Thread.sleep(1*1000);

            }


        } catch (Exception e){

            String errMsg = e.getMessage();
            if(errMsg == null){
                errMsg = "双车加料任务运行出错，请查看日志";
            }
            TaskExecutionWebSocketService socketService = SpringUtils.getBean(TaskExecutionWebSocketService.class);
            Map map = new HashMap(2);
            map.put("code","20");
            map.put("data",macSN+":执行任务id:"+idKey+",出现异常。出错原因："+errMsg);
            socketService.sendMessage(map);

            errMsg = errMsg.length() > 200 ? errMsg.substring(0,200) : errMsg;
            SysAddDetailTaskEntity errEntity = SysAddDetailTaskEntity.builder().idKey(idKey)
                    .status(TaskStatusEnum.STATUS_ERROR.getStatus()).errMsg(errMsg).build();
            sysAddDetailTaskService.updateById(errEntity);
            SysTaskErrorInfoEntity sysTaskErrorInfoEntity = SysTaskErrorInfoEntity.builder().taskId(taskMaterialBO.getTaskId()).carName(carPLCInfoEnum.getMacSN()).errMsg(errMsg).build();
            ThreadPoolManager.getInstance().execute(AddTaskRecordErrorInfoThread.builder().taskErrorInfoEntity(sysTaskErrorInfoEntity).build());
            //天车执行执行复位
            Object[] carExecuteInfo = carPLCInfoEnum.getPLCInfoArray()[5];
            PLCWriteRequestParamBO paramBO = PLCWriteRequestParamBO.builder().dataType((Integer) carExecuteInfo[1])
                    .address((String) carExecuteInfo[0]).macSN(macSN).label((String) carExecuteInfo[2]).build();
            paramBO.setValue(AddTaskConstant.CAR_FORBID_MOVE);

            try {

                PLCHttpsUtils.write(RemoteURLConstant.URL_WRITEBC,paramBO);
            } catch (Exception exception){

            }
            log.error("CarDoingSingleAddTaskThread running error",e);
        } finally {
            taskFinishFlag = true;
        }

    }


    private void writeMoreVal(CarPLCInfoEnum plcInfoEnum,String taskType,String taskPlace,Coord coord) throws Exception {
        //plcInfoArray  二维数组  大车目标坐标[] 小车目标坐标[]  起升目标坐标[] 作业类型[]  作业地址[] 任务运行[]

        Object[][] plcInfoArray = plcInfoEnum.getPLCInfoArray();
        for(int i = 0;i < plcInfoArray.length;i++){
            //info  一位数组[地址,数据类型,label]
            Object[] info = plcInfoArray[i];
            //设置value
            String value = this.getValue(taskType,taskPlace,coord,i);
            PLCWriteRequestParamBO paramBO = PLCWriteRequestParamBO.builder().macSN(plcInfoEnum.getMacSN()).address((String) info[0])
                    .dataType((Integer) info[1]).label((String) info[2]).build();
            paramBO.setValue(value);
            if(i == 5){
                //当写任务运行时,先读取数据，判断数值是否都写成功了
                for(int j = 0;j < i;j++){
                    Object[] readInfo = plcInfoArray[j];
                    Map<String, String> snMap = SystemUtils.Sys_carInfo.get(ConfigConstant.CONFIG_TYPE_CAR_BAK_SN);
                    String sn = snMap.get(plcInfoEnum.getMacSN());
                    String target = this.getValue(taskType, taskPlace, coord, j);
                    boolean isSuccess = PLCHttpsUtils.valIsSuccess(sn, (String) readInfo[2], target);
                    if(!isSuccess){
                        PLCWriteRequestParamBO secondParamBO = PLCWriteRequestParamBO.builder().macSN(plcInfoEnum.getMacSN()).address((String) readInfo[0])
                                .dataType((Integer) readInfo[1]).label((String) readInfo[2]).build();
                        secondParamBO.setValue(this.getValue(taskType,taskPlace,coord,j));
                        PLCHttpsUtils.write(RemoteURLConstant.URL_WRITEBC,secondParamBO);
                    }
                }
                PLCHttpsUtils.write(RemoteURLConstant.URL_WRITEBC,paramBO);
            } else {
                PLCHttpsUtils.writeMoreVal(RemoteURLConstant.URL_WRITEBC,paramBO);
            }
        }
    }

    private void writeOpt(Object[] info, String value,String macSN) throws Exception {

        //info  一位数组[地址,数据类型,label]
        PLCWriteRequestParamBO paramBO = PLCWriteRequestParamBO.builder().macSN(macSN).address((String) info[0])
                .dataType((Integer) info[1]).label((String) info[2]).build();

        paramBO.setValue(value);
        PLCHttpsUtils.write(RemoteURLConstant.URL_WRITEBC,paramBO);

    }


    private void goSafePosition(CarPLCInfoEnum carPLCInfoEnum) throws Exception {

        Object[][] safeArray = carPLCInfoEnum.getCarSafeIndexEnum().getSafeArray();
        for(int i = 0;i < safeArray.length;i++){
            //info  一位数组[地址,数据类型,label]
            Object[] info = safeArray[i];
            PLCWriteRequestParamBO paramBO = PLCWriteRequestParamBO.builder().macSN(carPLCInfoEnum.getMacSN()).address((String) info[0])
                    .dataType((Integer) info[1]).label((String) info[2]).build();
            paramBO.setValue(String.valueOf(info[3]));
            if(i == 5){
                //当写任务运行时,先读取数据，判断数值是否都写成功了
                for(int j = 0;j < i;j++){
                    Object[] readInfo = safeArray[j];
                    Map<String, String> snMap = SystemUtils.Sys_carInfo.get(ConfigConstant.CONFIG_TYPE_CAR_BAK_SN);
                    String sn = snMap.get(carPLCInfoEnum.getMacSN());
                    String target = String.valueOf(readInfo[3]);
                    boolean isSuccess = PLCHttpsUtils.valIsSuccess(sn, (String) readInfo[2], target);
                    if(!isSuccess){
                        PLCWriteRequestParamBO secondParamBO = PLCWriteRequestParamBO.builder().macSN(carPLCInfoEnum.getMacSN()).address((String) readInfo[0])
                                .dataType((Integer) readInfo[1]).label((String) readInfo[2]).build();
                        secondParamBO.setValue(target);
                        PLCHttpsUtils.write(RemoteURLConstant.URL_WRITEBC,secondParamBO);
                    }
                }
                PLCHttpsUtils.write(RemoteURLConstant.URL_WRITEBC,paramBO);
            } else {
                PLCHttpsUtils.writeMoreVal(RemoteURLConstant.URL_WRITEBC,paramBO);
            }
        }

    }





    private String getValue(String taskType, String taskPlace, Coord grabPoint,int i) {

        switch (i){
            case 0:
                return String.valueOf(grabPoint.getX());
            case 1:
                return String.valueOf(grabPoint.getY());
            case 2:
                return String.valueOf(grabPoint.getZ());
            case 3:
                return taskType;
            case 4:
                return taskPlace;
            case 5:
                return AddTaskConstant.CAR_ALLOW_MOVE;
        }
        return null;
    }


    private String getValByLabel(Map<String, String> paramMap) throws IOException {

        ResponseLabelDataBO responseLabelDataBO;
        responseLabelDataBO = PLCHttpsUtils.sendPost(RemoteURLConstant.URL_READBC, paramMap, ResponseLabelDataBO.class);
        Map<String, String> content1 = responseLabelDataBO.getContent();
        String res = content1 != null ? content1.get("currentVal").toLowerCase(): null;
        return res;
    }


    /**
     * 判断辆车的目标位置是否冲突
     * @param curCar
     * @param curPosition
     * @param otherPosition
     * @return  true:没有冲突   false：有冲突
     */
    private boolean comparePosition(CarEnum curCar,int curPosition,Integer otherPosition){


        //todo i为安全距离
        int i = AddTaskConstant.SAFE_DISTANCE;
        if(otherPosition == null){
            //空值代表暂时没有移动，另一台车在安全位置
            return true;
        }
        if(curCar.getCarNo() == CarEnum.CAR_NO_1.getCarNo()){
            //代表当前天车为右侧天车
            if(curPosition > otherPosition &&  curPosition - otherPosition >= i){
                return true;
            }


            return false;
        } else {
            //代表当前天车为左侧天车
            if(curPosition < otherPosition &&  otherPosition - curPosition >= i){
                return true;
            }
            return false;
        }
    }

}
